<!DOCTYPE html>
<html lang="zh_CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <meta name="generator" content="VuePress 2.0.0-beta.45">
    <style>
      :root {
        --c-bg: #fff;
      }
      html.dark {
        --c-bg: #22272e;
      }
      html, body {
        background-color: var(--c-bg);
      }
    </style>
    <script>
      const userMode = localStorage.getItem('vuepress-color-scheme');
			const systemDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
			if (userMode === 'dark' || (userMode !== 'light' && systemDarkMode)) {
				document.documentElement.classList.toggle('dark', true);
			}
    </script>
    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico"><title>viper 中文文档 | 科科人神</title><meta name="description" content="科科人神，后端软件工程师，喜欢云原生">
    <link rel="modulepreload" href="/assets/app.80e5dc69.js"><link rel="modulepreload" href="/assets/index.html.711c721b.js"><link rel="modulepreload" href="/assets/index.html.9d71a6d6.js"><link rel="prefetch" href="/assets/index.html.cba988ab.js"><link rel="prefetch" href="/assets/1.html.8ac90e92.js"><link rel="prefetch" href="/assets/19.html.4444be95.js"><link rel="prefetch" href="/assets/必备知识.html.7da85c42.js"><link rel="prefetch" href="/assets/必备知识罗列.html.5e18db77.js"><link rel="prefetch" href="/assets/1.html.356f0755.js"><link rel="prefetch" href="/assets/2.html.085440fc.js"><link rel="prefetch" href="/assets/3.html.09effb5c.js"><link rel="prefetch" href="/assets/1.html.50fb5135.js"><link rel="prefetch" href="/assets/1.html.17222973.js"><link rel="prefetch" href="/assets/1.html.0a197ef1.js"><link rel="prefetch" href="/assets/4-1.html.073fbd99.js"><link rel="prefetch" href="/assets/4-2.html.64039343.js"><link rel="prefetch" href="/assets/4.html.021c0881.js"><link rel="prefetch" href="/assets/5-6-1.html.34978ed1.js"><link rel="prefetch" href="/assets/5-6-2.html.f004f560.js"><link rel="prefetch" href="/assets/5-6.html.f5ad3835.js"><link rel="prefetch" href="/assets/index.html.467e6eba.js"><link rel="prefetch" href="/assets/index.html.f3622043.js"><link rel="prefetch" href="/assets/index.html.a2792a89.js"><link rel="prefetch" href="/assets/index.html.5d63961d.js"><link rel="prefetch" href="/assets/index.html.0b5fc023.js"><link rel="prefetch" href="/assets/index.html.2f735cf1.js"><link rel="prefetch" href="/assets/bash_completions.html.ed68147e.js"><link rel="prefetch" href="/assets/man_docs.html.2f0dd0c9.js"><link rel="prefetch" href="/assets/md_docs.html.20de452a.js"><link rel="prefetch" href="/assets/rest_docs.html.b77e8a2e.js"><link rel="prefetch" href="/assets/zsh_completions.html.60976ab2.js"><link rel="prefetch" href="/assets/syslog.html.48554683.js"><link rel="prefetch" href="/assets/daily_dep.html.2f155f5c.js"><link rel="prefetch" href="/assets/getting_started.html.769a2eaa.js"><link rel="prefetch" href="/assets/installation.html.e6b0002b.js"><link rel="prefetch" href="/assets/migrating.html.128871c1.js"><link rel="prefetch" href="/assets/new_project.html.8326d390.js"><link rel="prefetch" href="/assets/uninstalling.html.26650652.js"><link rel="prefetch" href="/assets/deduction.html.d4acd3fa.js"><link rel="prefetch" href="/assets/ensure_mechanics.html.603c62de.js"><link rel="prefetch" href="/assets/404.html.a15b4cbd.js"><link rel="prefetch" href="/assets/index.html.29aac47c.js"><link rel="prefetch" href="/assets/index.html.b64fbb23.js"><link rel="prefetch" href="/assets/index.html.cd48e230.js"><link rel="prefetch" href="/assets/index.html.6b048e76.js"><link rel="prefetch" href="/assets/index.html.7f0a6e54.js"><link rel="prefetch" href="/assets/index.html.b5a71586.js"><link rel="prefetch" href="/assets/index.html.60805430.js"><link rel="prefetch" href="/assets/index.html.60736b0b.js"><link rel="prefetch" href="/assets/index.html.80dddd6d.js"><link rel="prefetch" href="/assets/index.html.cc3c6a0d.js"><link rel="prefetch" href="/assets/index.html.44e62fda.js"><link rel="prefetch" href="/assets/index.html.015a0b2c.js"><link rel="prefetch" href="/assets/index.html.415d4517.js"><link rel="prefetch" href="/assets/index.html.d1d65e23.js"><link rel="prefetch" href="/assets/index.html.725ac526.js"><link rel="prefetch" href="/assets/index.html.c824ee30.js"><link rel="prefetch" href="/assets/1.html.4fb25663.js"><link rel="prefetch" href="/assets/19.html.ded8a9c9.js"><link rel="prefetch" href="/assets/必备知识.html.0ff3a77d.js"><link rel="prefetch" href="/assets/必备知识罗列.html.85e0f635.js"><link rel="prefetch" href="/assets/1.html.4f76037b.js"><link rel="prefetch" href="/assets/2.html.05a6e91e.js"><link rel="prefetch" href="/assets/3.html.30d4c4b6.js"><link rel="prefetch" href="/assets/1.html.ce86a757.js"><link rel="prefetch" href="/assets/1.html.0f8a9434.js"><link rel="prefetch" href="/assets/1.html.f4ee2fe7.js"><link rel="prefetch" href="/assets/4-1.html.c7cc75b6.js"><link rel="prefetch" href="/assets/4-2.html.36807608.js"><link rel="prefetch" href="/assets/4.html.c03ae622.js"><link rel="prefetch" href="/assets/5-6-1.html.651e5517.js"><link rel="prefetch" href="/assets/5-6-2.html.5ccfdb5e.js"><link rel="prefetch" href="/assets/5-6.html.882bc951.js"><link rel="prefetch" href="/assets/index.html.9d9ba895.js"><link rel="prefetch" href="/assets/index.html.3da373d1.js"><link rel="prefetch" href="/assets/index.html.6ec0b380.js"><link rel="prefetch" href="/assets/index.html.f8c39be7.js"><link rel="prefetch" href="/assets/index.html.e8d4dc57.js"><link rel="prefetch" href="/assets/index.html.2275c56f.js"><link rel="prefetch" href="/assets/bash_completions.html.31fa6426.js"><link rel="prefetch" href="/assets/man_docs.html.cc0f68c6.js"><link rel="prefetch" href="/assets/md_docs.html.dd10674f.js"><link rel="prefetch" href="/assets/rest_docs.html.46da86e5.js"><link rel="prefetch" href="/assets/zsh_completions.html.64d57b81.js"><link rel="prefetch" href="/assets/syslog.html.5324d692.js"><link rel="prefetch" href="/assets/daily_dep.html.b7a8b70b.js"><link rel="prefetch" href="/assets/getting_started.html.29c6534a.js"><link rel="prefetch" href="/assets/installation.html.b11da95a.js"><link rel="prefetch" href="/assets/migrating.html.92825adc.js"><link rel="prefetch" href="/assets/new_project.html.8fcfe511.js"><link rel="prefetch" href="/assets/uninstalling.html.34c1a6fb.js"><link rel="prefetch" href="/assets/deduction.html.2f0a618b.js"><link rel="prefetch" href="/assets/ensure_mechanics.html.7818d8b5.js"><link rel="prefetch" href="/assets/404.html.37719150.js"><link rel="prefetch" href="/assets/index.html.bc2fbcdd.js"><link rel="prefetch" href="/assets/index.html.2363e42b.js"><link rel="prefetch" href="/assets/index.html.691f6b43.js"><link rel="prefetch" href="/assets/index.html.c73599f4.js"><link rel="prefetch" href="/assets/index.html.32559aa6.js"><link rel="prefetch" href="/assets/index.html.283a60cc.js"><link rel="prefetch" href="/assets/index.html.b72bddc9.js"><link rel="prefetch" href="/assets/index.html.aebed871.js"><link rel="prefetch" href="/assets/index.html.1bace120.js"><link rel="prefetch" href="/assets/index.html.7913d44a.js"><link rel="prefetch" href="/assets/index.html.4e5360d4.js"><link rel="prefetch" href="/assets/index.html.028748b8.js"><link rel="prefetch" href="/assets/index.html.e9cb3a86.js"><link rel="prefetch" href="/assets/index.html.e31e8159.js"><link rel="prefetch" href="/assets/index.html.01049197.js"><link rel="prefetch" href="/assets/404.30cc8863.js"><link rel="prefetch" href="/assets/HomePage.4e823a0b.js"><link rel="prefetch" href="/assets/Layout.61f5e0fd.js"><link rel="prefetch" href="/assets/Links.8680cda6.js"><link rel="prefetch" href="/assets/Post.93b09438.js"><link rel="prefetch" href="/assets/Tags.3d9bb337.js">
    <link rel="stylesheet" href="/assets/style.8b24233a.css">
  </head>
  <body>
    <div id="app"><!--[--><div class="theme-container"><!--[--><header class="navbar is-fixed is-visible invert"><span><a href="/" class=""><span class="site-name">$ cd /home/</span></a></span><div class="navbar-items-wrapper" style=""><!--[--><!--]--><nav class="navbar-items can-hide"><!--[--><div class="navbar-item"><a href="/" class="" aria-label="home"><!--[--><!--]--><span class="nav-icon"><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="0 0 20 20" fill="currentColor"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"/></svg></span><span>home</span><!--[--><!--]--></a></div><div class="navbar-item"><a href="/tags/" class="" aria-label="归档"><!--[--><!--]--><span class="nav-icon"><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="-1.6 -1.6 19.2 19.2" fill="currentColor"><path d="M2 2a1 1 0 011-1h4.586a1 1 0 01.707.293l7 7a1 1 0 010 1.414l-4.586 4.586a1 1 0 01-1.414 0l-7-7A1 1 0 012 6.586V2zm3.5 4a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"/><path d="M1.293 7.793A1 1 0 011 7.086V2a1 1 0 00-1 1v4.586a1 1 0 00.293.707l7 7a1 1 0 001.414 0l.043-.043-7.457-7.457z"/></svg></span><span>归档</span><!--[--><!--]--></a></div><div class="navbar-item"><a href="/links/" class="" aria-label="作品合集"><!--[--><!--]--><span class="nav-icon"><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="-79.52 -43.52 599.04 599.04" fill="currentColor"><path d="M382.7 292.5l2.7 2.7-170-167.3c-3.5-3.5-9.7-3.7-13.8-.5L144.3 171c-4.2 3.2-4.6 8.7-1.1 12.2l68.1 64.3c3.6 3.5 9.9 3.7 14 .5l.1-.1c4.1-3.2 10.4-3 14 .5l84 81.3c3.6 3.5 3.2 9-.9 12.2l-93.2 74c-4.2 3.3-10.5 3.1-14.2-.4L63.2 268c-3.5-3.5-9.7-3.7-13.9-.5L3.5 302.4c-4.2 3.2-4.7 8.7-1.2 12.2L211 510.7s7.4 6.8 17.3-.8l198-163.9c4-3.2 4.4-8.7.7-12.2zm54.5-83.4L226.7 2.5c-1.5-1.2-8-5.5-16.3 1.1L3.6 165.7c-4.2 3.2-4.8 8.7-1.2 12.2l42.3 41.7 171.7 165.1c3.7 3.5 10.1 3.7 14.3.4l50.2-38.8-.3-.3 7.7-6c4.2-3.2 4.6-8.7.9-12.2l-57.1-54.4c-3.6-3.5-10-3.7-14.2-.5l-.1.1c-4.2 3.2-10.5 3.1-14.2-.4L109 180.8c-3.6-3.5-3.1-8.9 1.1-12.2l92.2-71.5c4.1-3.2 10.3-3 13.9.5l160.4 159c3.7 3.5 10 3.7 14.1.5l45.8-35.8c4.1-3.2 4.4-8.7.7-12.2z"/></svg></span><span>作品合集</span><!--[--><!--]--></a></div><!--]--><div class="navbar-item"><a style="cursor:pointer;"><span class="nav-icon"><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="0 0 24 24" fill="currentColor"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 2c4.968 0 9 4.032 9 9s-4.032 9-9 9-9-4.032-9-9 4.032-9 9-9zm0 16c3.867 0 7-3.133 7-7 0-3.868-3.133-7-7-7-3.868 0-7 3.132-7 7 0 3.867 3.132 7 7 7zm8.485.071l2.829 2.828-1.415 1.415-2.828-2.829 1.414-1.414z"/></svg></span><span>搜索</span></a></div></nav><!--[--><!--]--><!----></div></header><!--]--><div class="sidebar-mask"></div><!--[--><aside class="sidebar"><nav class="navbar-items"><!--[--><div class="navbar-item"><a href="/" class="" aria-label="home"><!--[--><!--]--><span class="nav-icon"><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="0 0 20 20" fill="currentColor"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"/></svg></span><span>home</span><!--[--><!--]--></a></div><div class="navbar-item"><a href="/tags/" class="" aria-label="归档"><!--[--><!--]--><span class="nav-icon"><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="-1.6 -1.6 19.2 19.2" fill="currentColor"><path d="M2 2a1 1 0 011-1h4.586a1 1 0 01.707.293l7 7a1 1 0 010 1.414l-4.586 4.586a1 1 0 01-1.414 0l-7-7A1 1 0 012 6.586V2zm3.5 4a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"/><path d="M1.293 7.793A1 1 0 011 7.086V2a1 1 0 00-1 1v4.586a1 1 0 00.293.707l7 7a1 1 0 001.414 0l.043-.043-7.457-7.457z"/></svg></span><span>归档</span><!--[--><!--]--></a></div><div class="navbar-item"><a href="/links/" class="" aria-label="作品合集"><!--[--><!--]--><span class="nav-icon"><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="-79.52 -43.52 599.04 599.04" fill="currentColor"><path d="M382.7 292.5l2.7 2.7-170-167.3c-3.5-3.5-9.7-3.7-13.8-.5L144.3 171c-4.2 3.2-4.6 8.7-1.1 12.2l68.1 64.3c3.6 3.5 9.9 3.7 14 .5l.1-.1c4.1-3.2 10.4-3 14 .5l84 81.3c3.6 3.5 3.2 9-.9 12.2l-93.2 74c-4.2 3.3-10.5 3.1-14.2-.4L63.2 268c-3.5-3.5-9.7-3.7-13.9-.5L3.5 302.4c-4.2 3.2-4.7 8.7-1.2 12.2L211 510.7s7.4 6.8 17.3-.8l198-163.9c4-3.2 4.4-8.7.7-12.2zm54.5-83.4L226.7 2.5c-1.5-1.2-8-5.5-16.3 1.1L3.6 165.7c-4.2 3.2-4.8 8.7-1.2 12.2l42.3 41.7 171.7 165.1c3.7 3.5 10.1 3.7 14.3.4l50.2-38.8-.3-.3 7.7-6c4.2-3.2 4.6-8.7.9-12.2l-57.1-54.4c-3.6-3.5-10-3.7-14.2-.5l-.1.1c-4.2 3.2-10.5 3.1-14.2-.4L109 180.8c-3.6-3.5-3.1-8.9 1.1-12.2l92.2-71.5c4.1-3.2 10.3-3 13.9.5l160.4 159c3.7 3.5 10 3.7 14.1.5l45.8-35.8c4.1-3.2 4.4-8.7.7-12.2z"/></svg></span><span>作品合集</span><!--[--><!--]--></a></div><!--]--><div class="navbar-item"><a style="cursor:pointer;"><span class="nav-icon"><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="0 0 24 24" fill="currentColor"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 2c4.968 0 9 4.032 9 9s-4.032 9-9 9-9-4.032-9-9 4.032-9 9-9zm0 16c3.867 0 7-3.133 7-7 0-3.868-3.133-7-7-7-3.868 0-7 3.132-7 7 0 3.867 3.132 7 7 7zm8.485.071l2.829 2.828-1.415 1.415-2.828-2.829 1.414-1.414z"/></svg></span><span>搜索</span></a></div></nav><!--[--><!--]--><ul class="sidebar-items"><!--[--><li><p tabindex="0" class="sidebar-item sidebar-heading">viper 中文文档 <!----></p><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/posts/2023/4/docs/viper/#viper是什么" class="router-link-active router-link-exact-active sidebar-item" aria-label="Viper是什么？"><!--[--><!--]--><!----><span>Viper是什么？</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#为什么选择-viper" class="router-link-active router-link-exact-active sidebar-item" aria-label="为什么选择 Viper?"><!--[--><!--]--><!----><span>为什么选择 Viper?</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#将值放入-viper" class="router-link-active router-link-exact-active sidebar-item" aria-label="将值放入 Viper"><!--[--><!--]--><!----><span>将值放入 Viper</span><!--[--><!--]--></a><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/posts/2023/4/docs/viper/#建立默认值" class="router-link-active router-link-exact-active sidebar-item" aria-label="建立默认值"><!--[--><!--]--><!----><span>建立默认值</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#读取配置文件" class="router-link-active router-link-exact-active sidebar-item" aria-label="读取配置文件"><!--[--><!--]--><!----><span>读取配置文件</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#监听和重新读取配置文件" class="router-link-active router-link-exact-active sidebar-item" aria-label="监听和重新读取配置文件"><!--[--><!--]--><!----><span>监听和重新读取配置文件</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#从-io-reader-读取配置" class="router-link-active router-link-exact-active sidebar-item" aria-label="从 io.Reader 读取配置"><!--[--><!--]--><!----><span>从 io.Reader 读取配置</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#覆盖设置" class="router-link-active router-link-exact-active sidebar-item" aria-label="覆盖设置"><!--[--><!--]--><!----><span>覆盖设置</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#注册和使用别名" class="router-link-active router-link-exact-active sidebar-item" aria-label="注册和使用别名"><!--[--><!--]--><!----><span>注册和使用别名</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#使用环境变量" class="router-link-active router-link-exact-active sidebar-item" aria-label="使用环境变量"><!--[--><!--]--><!----><span>使用环境变量</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#使用标志" class="router-link-active router-link-exact-active sidebar-item" aria-label="使用标志"><!--[--><!--]--><!----><span>使用标志</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#远程-key-value-存储支持" class="router-link-active router-link-exact-active sidebar-item" aria-label="远程 Key/Value 存储支持"><!--[--><!--]--><!----><span>远程 Key/Value 存储支持</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#remote-key-value-store-example-unencrypted" class="router-link-active router-link-exact-active sidebar-item" aria-label="Remote Key/Value Store Example - Unencrypted"><!--[--><!--]--><!----><span>Remote Key/Value Store Example - Unencrypted</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#remote-key-value-store-example-encrypted" class="router-link-active router-link-exact-active sidebar-item" aria-label="Remote Key/Value Store Example - Encrypted"><!--[--><!--]--><!----><span>Remote Key/Value Store Example - Encrypted</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#watching-changes-in-etcd-unencrypted" class="router-link-active router-link-exact-active sidebar-item" aria-label="Watching Changes in etcd - Unencrypted"><!--[--><!--]--><!----><span>Watching Changes in etcd - Unencrypted</span><!--[--><!--]--></a><!----></li><!--]--></ul></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#getting-values-from-viper" class="router-link-active router-link-exact-active sidebar-item" aria-label="Getting Values From Viper"><!--[--><!--]--><!----><span>Getting Values From Viper</span><!--[--><!--]--></a><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/posts/2023/4/docs/viper/#accessing-nested-keys" class="router-link-active router-link-exact-active sidebar-item" aria-label="Accessing nested keys"><!--[--><!--]--><!----><span>Accessing nested keys</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#extract-sub-tree" class="router-link-active router-link-exact-active sidebar-item" aria-label="Extract sub-tree"><!--[--><!--]--><!----><span>Extract sub-tree</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#unmarshaling" class="router-link-active router-link-exact-active sidebar-item" aria-label="Unmarshaling"><!--[--><!--]--><!----><span>Unmarshaling</span><!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#marshalling-to-string" class="router-link-active router-link-exact-active sidebar-item" aria-label="Marshalling to string"><!--[--><!--]--><!----><span>Marshalling to string</span><!--[--><!--]--></a><!----></li><!--]--></ul></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#viper-还是-vipers" class="router-link-active router-link-exact-active sidebar-item" aria-label="Viper 还是 Vipers?"><!--[--><!--]--><!----><span>Viper 还是 Vipers?</span><!--[--><!--]--></a><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/posts/2023/4/docs/viper/#working-with-multiple-vipers" class="router-link-active router-link-exact-active sidebar-item" aria-label="Working with multiple vipers"><!--[--><!--]--><!----><span>Working with multiple vipers</span><!--[--><!--]--></a><!----></li><!--]--></ul></li><li><a aria-current="page" href="/posts/2023/4/docs/viper/#q-a" class="router-link-active router-link-exact-active sidebar-item" aria-label="Q &amp; A"><!--[--><!--]--><!----><span>Q &amp; A</span><!--[--><!--]--></a><!----></li><!--]--></ul></li><!--]--></ul><!--[--><!--]--></aside><!--]--><div class="page-content"><!--[--><main class="page"><!--[--><div class="article-header" style=""><!----><div class="article-header-content"><!----><h1 class="article-title"></h1><!----><div class="article-icons"><div class="article-icon"><svg class="ov-icon" style="font-size:1.08em;" aria-hidden="true" width="17.28" height="17.28" viewbox="-75.52 -43.52 599.04 599.04" fill="currentColor"><path d="M313.6 304c-28.7 0-42.5 16-89.6 16-47.1 0-60.8-16-89.6-16C60.2 304 0 364.2 0 438.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-25.6c0-74.2-60.2-134.4-134.4-134.4zM400 464H48v-25.6c0-47.6 38.8-86.4 86.4-86.4 14.6 0 38.3 16 89.6 16 51.7 0 74.9-16 89.6-16 47.6 0 86.4 38.8 86.4 86.4V464zM224 288c79.5 0 144-64.5 144-144S303.5 0 224 0 80 64.5 80 144s64.5 144 144 144zm0-240c52.9 0 96 43.1 96 96s-43.1 96-96 96-96-43.1-96-96 43.1-96 96-96z"/></svg><span>科科人神</span></div><!----><div class="article-icon"><svg class="ov-icon" style="font-size:1.08em;" aria-hidden="true" width="17.28" height="17.28" viewbox="0 0 24 24" fill="currentColor"><path fill="none" d="M0 0h24v24H0z"/><path d="M17.618 5.968l1.453-1.453 1.414 1.414-1.453 1.453a9 9 0 11-1.414-1.414zM12 20a7 7 0 100-14 7 7 0 000 14zM11 8h2v6h-2V8zM8 1h8v2H8V1z"/></svg><span>18 min</span></div></div></div><!----></div><!--[--><!--]--><!--]--><div class="theme-gungnir-content"><!--[--><!--]--><!--[--><h1 id="viper-中文文档" tabindex="-1"><a class="header-anchor" href="#viper-中文文档" aria-hidden="true">#</a> viper 中文文档</h1><p>viper 中文文档，本文档基于 <a href="https://github.com/spf13/viper" target="_blank" rel="noopener noreferrer">viper</a> 官方文档。不定期更新。</p><p><img src="https://cloud.githubusercontent.com/assets/173412/10886745/998df88a-8151-11e5-9448-4736db51020d.png" alt="viper logo"></p><p>Go 使用 fangs 配置！</p><p>许多 Go 项目使用 Viper 构建，包括：</p><ul><li><a href="http://gohugo.io" target="_blank" rel="noopener noreferrer">Hugo</a></li><li><a href="http://rexray.readthedocs.org/en/stable/" target="_blank" rel="noopener noreferrer">EMC RexRay</a></li><li><a href="https://github.com/Imgur/incus" target="_blank" rel="noopener noreferrer">Imgur’s Incus</a></li><li><a href="https://github.com/nanobox-io/nanobox" target="_blank" rel="noopener noreferrer">Nanobox</a>/<a href="https://github.com/nanopack" target="_blank" rel="noopener noreferrer">Nanopack</a></li><li><a href="https://github.com/docker/Notary" target="_blank" rel="noopener noreferrer">Docker Notary</a></li><li><a href="https://www.bloomapi.com/" target="_blank" rel="noopener noreferrer">BloomApi</a></li><li><a href="https://github.com/digitalocean/doctl" target="_blank" rel="noopener noreferrer">doctl</a></li><li><a href="https://github.com/jgsqware/clairctl" target="_blank" rel="noopener noreferrer">Clairctl</a></li></ul><p><a href="https://travis-ci.org/spf13/viper" target="_blank" rel="noopener noreferrer"><img src="https://travis-ci.org/spf13/viper.svg" alt="Build Status"></a> <a href="https://gitter.im/spf13/viper?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge" target="_blank" rel="noopener noreferrer"><img src="https://badges.gitter.im/Join Chat.svg" alt="Join the chat at https://gitter.im/spf13/viper"></a> <a href="https://godoc.org/github.com/spf13/viper" target="_blank" rel="noopener noreferrer"><img src="https://godoc.org/github.com/spf13/viper?status.svg" alt="GoDoc"></a></p><h2 id="viper是什么" tabindex="-1"><a class="header-anchor" href="#viper是什么" aria-hidden="true">#</a> Viper是什么？</h2><p>Viper 是 Go 应用程序的完整配置解决方案，包括 12-Factor 应用程序。它旨在在应用程序中工作，并可以处理所有类型的配置需求和格式。它支持：</p><ul><li>默认配置</li><li>从 JSON, TOML, YAML, HCL 和 Java 属性配置文件读取数据</li><li>实时查看和重新读取配置文件（可选）</li><li>从环境变量中读取</li><li>从远程配置系统(etcd 或 Consul)读取数据并监听变化</li><li>从命令行参数读取</li><li>从 buffer 中读取</li><li>设置显式值</li></ul><p>Viper 可以被认为是所有应用程序配置需求的注册表。</p><h2 id="为什么选择-viper" tabindex="-1"><a class="header-anchor" href="#为什么选择-viper" aria-hidden="true">#</a> 为什么选择 Viper?</h2><p>当你构建现代应用程序时，不必担心配置文件格式; 你想专注于构建超赞的软件。Viper 就是为此提供帮助的。</p><p>Viper 为你做了以下事情:</p><ol><li>以 JSON，TOML，YAML，HCL 或 Java 属性格式查找，加载和解组配置文件。</li><li>提供一种机制来为不同的配置选项设置默认值。</li><li>提供一种机制可以通过命令行标志指定的选项设置来覆盖值。</li><li>提供别名系统，轻松重命名参数，而不会破坏现有代码。</li><li>当用户提供命令行或配置文件与默认值相同时，可以轻松区分。</li></ol><p>Viper 使用以下优先级顺序。每个项目优先于其下方的项目</p><ul><li>explicit call to Set</li><li>flag</li><li>env</li><li>config</li><li>key/value store</li><li>default</li></ul><p><strong>Viper配置键不区分大小写</strong>。</p><h2 id="将值放入-viper" tabindex="-1"><a class="header-anchor" href="#将值放入-viper" aria-hidden="true">#</a> 将值放入 Viper</h2><h3 id="建立默认值" tabindex="-1"><a class="header-anchor" href="#建立默认值" aria-hidden="true">#</a> 建立默认值</h3><p>一个好的配置系统是支持默认值的。key 不需要默认值，但是当没有通过配置文件，环境变量，远程配置或标志设置 key 时，它是非常有用的。</p><p>例:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">SetDefault</span><span class="token punctuation">(</span><span class="token string">&quot;ContentDir&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;content&quot;</span><span class="token punctuation">)</span>
viper<span class="token punctuation">.</span><span class="token function">SetDefault</span><span class="token punctuation">(</span><span class="token string">&quot;LayoutDir&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;layouts&quot;</span><span class="token punctuation">)</span>
viper<span class="token punctuation">.</span><span class="token function">SetDefault</span><span class="token punctuation">(</span><span class="token string">&quot;Taxonomies&quot;</span><span class="token punctuation">,</span> <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">{</span><span class="token string">&quot;tag&quot;</span><span class="token punctuation">:</span> <span class="token string">&quot;tags&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;category&quot;</span><span class="token punctuation">:</span> <span class="token string">&quot;categories&quot;</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="读取配置文件" tabindex="-1"><a class="header-anchor" href="#读取配置文件" aria-hidden="true">#</a> 读取配置文件</h3><p>Viper 需要极少的配置让它知道去哪里查找配置文件。Viper 支持 JSON, TOML, YAML, HCL 和 Java 属性配置文件。Viper 可以搜索多个路径，但目前单个 Viper 实例仅 支持单个配置文件。Viper 不默认任何配置搜索路径，将默认决策留给应用程序。</p><p>以下是如何使用 Viper 搜索和读取配置文件的示例。不需要任何特定的路径，但是至少应该在需要配置文件的地方提供一个路径。</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">SetConfigName</span><span class="token punctuation">(</span><span class="token string">&quot;config&quot;</span><span class="token punctuation">)</span> <span class="token comment">// name of config file (without extension)</span>
viper<span class="token punctuation">.</span><span class="token function">AddConfigPath</span><span class="token punctuation">(</span><span class="token string">&quot;/etc/appname/&quot;</span><span class="token punctuation">)</span>   <span class="token comment">// path to look for the config file in</span>
viper<span class="token punctuation">.</span><span class="token function">AddConfigPath</span><span class="token punctuation">(</span><span class="token string">&quot;$HOME/.appname&quot;</span><span class="token punctuation">)</span>  <span class="token comment">// call multiple times to add many search paths</span>
viper<span class="token punctuation">.</span><span class="token function">AddConfigPath</span><span class="token punctuation">(</span><span class="token string">&quot;.&quot;</span><span class="token punctuation">)</span>               <span class="token comment">// optionally look for config in the working directory</span>
err <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">ReadInConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// Find and read the config file</span>
<span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> <span class="token comment">// Handle errors reading the config file</span>
	<span class="token function">panic</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">&quot;Fatal error config file: %s \n&quot;</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="监听和重新读取配置文件" tabindex="-1"><a class="header-anchor" href="#监听和重新读取配置文件" aria-hidden="true">#</a> 监听和重新读取配置文件</h3><p>Viper 支持在运行时让应用程序实时读取配置文件。</p><p>需要重新启动服务器才能使配置生效的日子已经一去不复返了，viper 支持的应用程序可以在运行时读取配置文件的更新而不会错过任何一个节拍。</p><p>只需告诉 viper 实例 <code>watchConfig</code> 即可。你可以选择为 Viper 提供当每次发生更改时运行的函数。</p><p><strong>确保在调用 <code>WatchConfig()</code> 之前添加所有的配置路径 <code>ConfigPath</code></strong></p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">WatchConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
viper<span class="token punctuation">.</span><span class="token function">OnConfigChange</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>e fsnotify<span class="token punctuation">.</span>Event<span class="token punctuation">)</span> <span class="token punctuation">{</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">&quot;Config file changed:&quot;</span><span class="token punctuation">,</span> e<span class="token punctuation">.</span>Name<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="从-io-reader-读取配置" tabindex="-1"><a class="header-anchor" href="#从-io-reader-读取配置" aria-hidden="true">#</a> 从 <code>io.Reader</code> 读取配置</h3><p>Viper 预定义了许多配置源，例如文件，环境变量，标志和远程 K/V 存储，但你不受它们的约束。你还可以实现自己的需要的配置源并将其提供给 viper。</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">SetConfigType</span><span class="token punctuation">(</span><span class="token string">&quot;yaml&quot;</span><span class="token punctuation">)</span> <span class="token comment">// or viper.SetConfigType(&quot;YAML&quot;)</span>

<span class="token comment">// any approach to require this configuration into your program.</span>
<span class="token keyword">var</span> yamlExample <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">byte</span><span class="token punctuation">(</span><span class="token string">`
Hacker: true
name: steve
hobbies:
- skateboarding
- snowboarding
- go
clothing:
  jacket: leather
  trousers: denim
age: 35
eyes : brown
beard: true
`</span><span class="token punctuation">)</span>

viper<span class="token punctuation">.</span><span class="token function">ReadConfig</span><span class="token punctuation">(</span>bytes<span class="token punctuation">.</span><span class="token function">NewBuffer</span><span class="token punctuation">(</span>yamlExample<span class="token punctuation">)</span><span class="token punctuation">)</span>

viper<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token string">&quot;name&quot;</span><span class="token punctuation">)</span> <span class="token comment">// this would be &quot;steve&quot;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="覆盖设置" tabindex="-1"><a class="header-anchor" href="#覆盖设置" aria-hidden="true">#</a> 覆盖设置</h3><p>这些可以来自命令行标志，也可以来自你自己的应用程序逻辑。</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">Set</span><span class="token punctuation">(</span><span class="token string">&quot;Verbose&quot;</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span>
viper<span class="token punctuation">.</span><span class="token function">Set</span><span class="token punctuation">(</span><span class="token string">&quot;LogFile&quot;</span><span class="token punctuation">,</span> LogFile<span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="注册和使用别名" tabindex="-1"><a class="header-anchor" href="#注册和使用别名" aria-hidden="true">#</a> 注册和使用别名</h3><p>别名允许多个键引用单个值</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">RegisterAlias</span><span class="token punctuation">(</span><span class="token string">&quot;loud&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;Verbose&quot;</span><span class="token punctuation">)</span>

viper<span class="token punctuation">.</span><span class="token function">Set</span><span class="token punctuation">(</span><span class="token string">&quot;verbose&quot;</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token comment">// same result as next line</span>
viper<span class="token punctuation">.</span><span class="token function">Set</span><span class="token punctuation">(</span><span class="token string">&quot;loud&quot;</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span>   <span class="token comment">// same result as prior line</span>

viper<span class="token punctuation">.</span><span class="token function">GetBool</span><span class="token punctuation">(</span><span class="token string">&quot;loud&quot;</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
viper<span class="token punctuation">.</span><span class="token function">GetBool</span><span class="token punctuation">(</span><span class="token string">&quot;verbose&quot;</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="使用环境变量" tabindex="-1"><a class="header-anchor" href="#使用环境变量" aria-hidden="true">#</a> 使用环境变量</h3><p>Viper 完全支持环境变量。这使得 12 factor 应用程序可以开箱即用。 五种方法可以帮助使用 ENV:</p><ul><li><code>AutomaticEnv()</code></li><li><code>BindEnv(string...) : error</code></li><li><code>SetEnvPrefix(string)</code></li><li><code>SetEnvKeyReplacer(string...) *strings.Replacer</code></li><li><code>AllowEmptyEnvVar(bool)</code></li></ul><p><em>在处理环境变量时，重要的是要认识到 Viper 将环境变量视为区分大小写的变量。</em></p><p>Viper 提供了一种机制来确保 ENV 变量是唯一的。通过使用 <code>SetEnvPrefix</code>，可以告诉 Viper 在读取环境变量时使用前缀。<code>BindEnv</code> 和 <code>AutomaticEnv</code> 都将使用此前缀。</p><p><code>BindEnv</code> 需要一个或两个参数。第一个参数是键名，第二个是环境变量的名称。环境变量的名称区分大小写。如果未提供 ENV 变量名，则 Viper 将自动假设键名与 ENV 变量名称匹配， 但 ENV 变量为 IN ALL CAPS。 当明确提供ENV变量名称时，它<strong>不会自动添加前缀</strong>。</p><p>使用 ENV 变量时要认识到的一件重要事情是每次访问时都会读取该值。当调用 <code>BindEnv</code> 时，Viper不会修复该值。</p><p><code>AutomaticEnv</code> 是一个强大的帮手，特别是与 <code>SetEnvPrefix</code> 结合使用时。每当发出 <code>viper.Get</code> 请求时，Viper 都会检查环境变量。它将适用以下规则。 它将检查一个环境变量，其名称与大写的键匹配，如果设置了 <code>EnvPrefix</code>，则以它为前缀。</p><p><code>SetEnvKeyReplacer</code> 允许你使用 <code>strings.Replacer</code> 对象来重写 Env 键。如果你想在 <code>Get()</code> 调用中使用 <code>-</code> 或者某些东西，但希望你的环境变量使用 <code>_</code> 分隔符， 这是很有用的。使用它的一个例子可以在 <code>viper_test.go</code> 中找到。</p><p>默认情况下，空环境变量被视为未设置，并将回退到下一个配置源。要设置空环境变量，请使用 <code>AllowEmptyEnv</code> 方法。</p><h4 id="环境变量例子" tabindex="-1"><a class="header-anchor" href="#环境变量例子" aria-hidden="true">#</a> 环境变量例子</h4><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code><span class="token function">SetEnvPrefix</span><span class="token punctuation">(</span><span class="token string">&quot;spf&quot;</span><span class="token punctuation">)</span> <span class="token comment">// will be uppercased automatically</span>
<span class="token function">BindEnv</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span>

os<span class="token punctuation">.</span><span class="token function">Setenv</span><span class="token punctuation">(</span><span class="token string">&quot;SPF_ID&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;13&quot;</span><span class="token punctuation">)</span> <span class="token comment">// typically done outside of the app</span>

id <span class="token operator">:=</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span> <span class="token comment">// 13</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="使用标志" tabindex="-1"><a class="header-anchor" href="#使用标志" aria-hidden="true">#</a> 使用标志</h3><p>Viper 能够绑定到标志。具体来说，Viper 支持 <a href="https://github.com/spf13/cobra" target="_blank" rel="noopener noreferrer">Cobra</a> 库中使用的 “Pflags”。</p><p>与 <code>BindEnv</code> 类似，在调用绑定方法时，不会设置该值。但在访问它时，会设置。这意味着你可以尽早绑定，即使在 <code>init()</code> 函数中也是如此。</p><p>对于单个标志，<code>BindPFlag()</code> 方法提供此功能。</p><p>例:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>serverCmd<span class="token punctuation">.</span><span class="token function">Flags</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Int</span><span class="token punctuation">(</span><span class="token string">&quot;port&quot;</span><span class="token punctuation">,</span> <span class="token number">1138</span><span class="token punctuation">,</span> <span class="token string">&quot;Port to run Application server on&quot;</span><span class="token punctuation">)</span>
viper<span class="token punctuation">.</span><span class="token function">BindPFlag</span><span class="token punctuation">(</span><span class="token string">&quot;port&quot;</span><span class="token punctuation">,</span> serverCmd<span class="token punctuation">.</span><span class="token function">Flags</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Lookup</span><span class="token punctuation">(</span><span class="token string">&quot;port&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><p>You can also bind an existing set of pflags (pflag.FlagSet):</p><p>例:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>pflag<span class="token punctuation">.</span><span class="token function">Int</span><span class="token punctuation">(</span><span class="token string">&quot;flagname&quot;</span><span class="token punctuation">,</span> <span class="token number">1234</span><span class="token punctuation">,</span> <span class="token string">&quot;help message for flagname&quot;</span><span class="token punctuation">)</span>

pflag<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
viper<span class="token punctuation">.</span><span class="token function">BindPFlags</span><span class="token punctuation">(</span>pflag<span class="token punctuation">.</span>CommandLine<span class="token punctuation">)</span>

i <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">GetInt</span><span class="token punctuation">(</span><span class="token string">&quot;flagname&quot;</span><span class="token punctuation">)</span> <span class="token comment">// retrieve values from viper instead of pflag</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在 Viper 中使用 <a href="https://github.com/spf13/pflag/" target="_blank" rel="noopener noreferrer">pflag</a> 并不排除使用标准库中使用 <a href="https://golang.org/pkg/flag/" target="_blank" rel="noopener noreferrer">flag</a> 包的其他包。 pflag 包可以通过导入这些标志来处理为 flag 包定义的标志。这是通过调用由的 pflag 包提供的名为 <code>AddGoFlagSet</code> 便利函数来实现的。</p><p>Example:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;flag&quot;</span>
	<span class="token string">&quot;github.com/spf13/pflag&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

	<span class="token comment">// using standard library &quot;flag&quot; package</span>
	flag<span class="token punctuation">.</span><span class="token function">Int</span><span class="token punctuation">(</span><span class="token string">&quot;flagname&quot;</span><span class="token punctuation">,</span> <span class="token number">1234</span><span class="token punctuation">,</span> <span class="token string">&quot;help message for flagname&quot;</span><span class="token punctuation">)</span>

	pflag<span class="token punctuation">.</span>CommandLine<span class="token punctuation">.</span><span class="token function">AddGoFlagSet</span><span class="token punctuation">(</span>flag<span class="token punctuation">.</span>CommandLine<span class="token punctuation">)</span>
	pflag<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	viper<span class="token punctuation">.</span><span class="token function">BindPFlags</span><span class="token punctuation">(</span>pflag<span class="token punctuation">.</span>CommandLine<span class="token punctuation">)</span>

	i <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">GetInt</span><span class="token punctuation">(</span><span class="token string">&quot;flagname&quot;</span><span class="token punctuation">)</span> <span class="token comment">// retrieve value from viper</span>

	<span class="token operator">...</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="flag-接口" tabindex="-1"><a class="header-anchor" href="#flag-接口" aria-hidden="true">#</a> Flag 接口</h4><p>如果你不使用 <code>Pflags</code>，Viper 提供两个 Go 接口来绑定其他标志系统。</p><p><code>FlagValue</code> 代表一个标志。 这是一个关于如何实现此接口的非常简单的示例:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> myFlag <span class="token keyword">struct</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>f myFlag<span class="token punctuation">)</span> <span class="token function">HasChanged</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">false</span> <span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>f myFlag<span class="token punctuation">)</span> <span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token string">&quot;my-flag-name&quot;</span> <span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>f myFlag<span class="token punctuation">)</span> <span class="token function">ValueString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token string">&quot;my-flag-value&quot;</span> <span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>f myFlag<span class="token punctuation">)</span> <span class="token function">ValueType</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token string">&quot;string&quot;</span> <span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>一旦你的标志实现了这个接口，你就可以告诉 Viper 绑定它:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">BindFlagValue</span><span class="token punctuation">(</span><span class="token string">&quot;my-flag-name&quot;</span><span class="token punctuation">,</span> myFlag<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p><code>FlagValueSet</code> represents a group of flags. This is a very simple example on how to implement this interface:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> myFlagSet <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	flags <span class="token punctuation">[</span><span class="token punctuation">]</span>myFlag
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>f myFlagSet<span class="token punctuation">)</span> <span class="token function">VisitAll</span><span class="token punctuation">(</span>fn <span class="token keyword">func</span><span class="token punctuation">(</span>FlagValue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> flag <span class="token operator">:=</span> <span class="token keyword">range</span> flags <span class="token punctuation">{</span>
		<span class="token function">fn</span><span class="token punctuation">(</span>flag<span class="token punctuation">)</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Once your flag set implements this interface, you can simply tell Viper to bind it:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>fSet <span class="token operator">:=</span> myFlagSet<span class="token punctuation">{</span>
	flags<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>myFlag<span class="token punctuation">{</span>myFlag<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> myFlag<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
viper<span class="token punctuation">.</span><span class="token function">BindFlagValues</span><span class="token punctuation">(</span><span class="token string">&quot;my-flags&quot;</span><span class="token punctuation">,</span> fSet<span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="远程-key-value-存储支持" tabindex="-1"><a class="header-anchor" href="#远程-key-value-存储支持" aria-hidden="true">#</a> 远程 Key/Value 存储支持</h3><p>要在 Viper 中启用远程支持，空白导入 <code>viper/remote</code> 软件包:</p><p><code>import _ &quot;github.com/spf13/viper/remote&quot;</code></p><p>Viper 将读取从 Key/Value 存储（如etcd或Consul）中的路径检索的配置字符串（如 JSON，TOML，YAML 或 HCL）。这些值优先于默认值， 但会被从磁盘，标志或环境变量检索的配置值覆盖。</p><p>Viper 使用 <a href="https://github.com/xordataexchange/crypt" target="_blank" rel="noopener noreferrer">crypt</a> 从 K/V 存储中检索配置，这意味着你可以存储加密的配置值， 并在拥有正确的 gpg 密钥环时自动解密它们。加密是可选的。</p><p>你可以将远程配置与本地配置结合使用，也可以独立使用。</p><p>你可以使用 <code>crypt</code> 命令行助手将你的配置放到到 K/V 存储。<code>crypt</code> 默认存储为 etcd，url 是 <code>http://127.0.0.1:4001</code>。</p><div class="language-bash ext-sh line-numbers-mode"><pre class="language-bash"><code>$ go get github.com/xordataexchange/crypt/bin/crypt
$ crypt <span class="token builtin class-name">set</span> -plaintext /config/hugo.json /Users/hugo/settings/config.json
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><p>确认你的值已设置：</p><div class="language-bash ext-sh line-numbers-mode"><pre class="language-bash"><code>$ crypt get -plaintext /config/hugo.json
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>有关如何设置加密值或如何使用 Consul 的示例，请参阅 <code>crypt</code> 文档。</p><h3 id="remote-key-value-store-example-unencrypted" tabindex="-1"><a class="header-anchor" href="#remote-key-value-store-example-unencrypted" aria-hidden="true">#</a> Remote Key/Value Store Example - Unencrypted</h3><h4 id="etcd" tabindex="-1"><a class="header-anchor" href="#etcd" aria-hidden="true">#</a> etcd</h4><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">AddRemoteProvider</span><span class="token punctuation">(</span><span class="token string">&quot;etcd&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;http://127.0.0.1:4001&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;/config/hugo.json&quot;</span><span class="token punctuation">)</span>
viper<span class="token punctuation">.</span><span class="token function">SetConfigType</span><span class="token punctuation">(</span><span class="token string">&quot;json&quot;</span><span class="token punctuation">)</span> <span class="token comment">// because there is no file extension in a stream of bytes, supported extensions are &quot;json&quot;, &quot;toml&quot;, &quot;yaml&quot;, &quot;yml&quot;, &quot;properties&quot;, &quot;props&quot;, &quot;prop&quot;</span>
err <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">ReadRemoteConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="consul" tabindex="-1"><a class="header-anchor" href="#consul" aria-hidden="true">#</a> Consul</h4><p>你需要使用包含所需配置的 JSON 值为 Consul K/V 存储 设置密钥。例如，使用下面的值创建一个 Consul K/V 存储 key 为 <code>MY_CONSUL_KEY</code>：</p><div class="language-json ext-json line-numbers-mode"><pre class="language-json"><code><span class="token punctuation">{</span>
    <span class="token property">&quot;port&quot;</span><span class="token operator">:</span> <span class="token number">8080</span><span class="token punctuation">,</span>
    <span class="token property">&quot;hostname&quot;</span><span class="token operator">:</span> <span class="token string">&quot;myhostname.com&quot;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">AddRemoteProvider</span><span class="token punctuation">(</span><span class="token string">&quot;consul&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;localhost:8500&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;MY_CONSUL_KEY&quot;</span><span class="token punctuation">)</span>
viper<span class="token punctuation">.</span><span class="token function">SetConfigType</span><span class="token punctuation">(</span><span class="token string">&quot;json&quot;</span><span class="token punctuation">)</span> <span class="token comment">// Need to explicitly set this to json</span>
err <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">ReadRemoteConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>viper<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token string">&quot;port&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 8080</span>
fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>viper<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token string">&quot;hostname&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// myhostname.com</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="remote-key-value-store-example-encrypted" tabindex="-1"><a class="header-anchor" href="#remote-key-value-store-example-encrypted" aria-hidden="true">#</a> Remote Key/Value Store Example - Encrypted</h3><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">AddSecureRemoteProvider</span><span class="token punctuation">(</span><span class="token string">&quot;etcd&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;http://127.0.0.1:4001&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;/config/hugo.json&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;/etc/secrets/mykeyring.gpg&quot;</span><span class="token punctuation">)</span>
viper<span class="token punctuation">.</span><span class="token function">SetConfigType</span><span class="token punctuation">(</span><span class="token string">&quot;json&quot;</span><span class="token punctuation">)</span> <span class="token comment">// because there is no file extension in a stream of bytes,  supported extensions are &quot;json&quot;, &quot;toml&quot;, &quot;yaml&quot;, &quot;yml&quot;, &quot;properties&quot;, &quot;props&quot;, &quot;prop&quot;</span>
err <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">ReadRemoteConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="watching-changes-in-etcd-unencrypted" tabindex="-1"><a class="header-anchor" href="#watching-changes-in-etcd-unencrypted" aria-hidden="true">#</a> Watching Changes in etcd - Unencrypted</h3><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code><span class="token comment">// alternatively, you can create a new viper instance.</span>
<span class="token keyword">var</span> runtime_viper <span class="token operator">=</span> viper<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

runtime_viper<span class="token punctuation">.</span><span class="token function">AddRemoteProvider</span><span class="token punctuation">(</span><span class="token string">&quot;etcd&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;http://127.0.0.1:4001&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;/config/hugo.yml&quot;</span><span class="token punctuation">)</span>
runtime_viper<span class="token punctuation">.</span><span class="token function">SetConfigType</span><span class="token punctuation">(</span><span class="token string">&quot;yaml&quot;</span><span class="token punctuation">)</span> <span class="token comment">// because there is no file extension in a stream of bytes, supported extensions are &quot;json&quot;, &quot;toml&quot;, &quot;yaml&quot;, &quot;yml&quot;, &quot;properties&quot;, &quot;props&quot;, &quot;prop&quot;</span>

<span class="token comment">// read from remote config the first time.</span>
err <span class="token operator">:=</span> runtime_viper<span class="token punctuation">.</span><span class="token function">ReadRemoteConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// unmarshal config</span>
runtime_viper<span class="token punctuation">.</span><span class="token function">Unmarshal</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>runtime_conf<span class="token punctuation">)</span>

<span class="token comment">// open a goroutine to watch remote changes forever</span>
<span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
	<span class="token keyword">for</span> <span class="token punctuation">{</span>
	    time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second <span class="token operator">*</span> <span class="token number">5</span><span class="token punctuation">)</span> <span class="token comment">// delay after each request</span>

	    <span class="token comment">// currently, only tested with etcd support</span>
	    err <span class="token operator">:=</span> runtime_viper<span class="token punctuation">.</span><span class="token function">WatchRemoteConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
	        log<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">&quot;unable to read remote config: %v&quot;</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
	        <span class="token keyword">continue</span>
	    <span class="token punctuation">}</span>

	    <span class="token comment">// unmarshal new config into our runtime config struct. you can also use channel</span>
	    <span class="token comment">// to implement a signal to notify the system of the changes</span>
	    runtime_viper<span class="token punctuation">.</span><span class="token function">Unmarshal</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>runtime_conf<span class="token punctuation">)</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="getting-values-from-viper" tabindex="-1"><a class="header-anchor" href="#getting-values-from-viper" aria-hidden="true">#</a> Getting Values From Viper</h2><p>在 Viper 中，有几种方法可以根据值的类型获取值。存在以下函数和方法：</p><ul><li><code>Get(key string) : interface{}</code></li><li><code>GetBool(key string) : bool</code></li><li><code>GetFloat64(key string) : float64</code></li><li><code>GetInt(key string) : int</code></li><li><code>GetString(key string) : string</code></li><li><code>GetStringMap(key string) : map[string]interface{}</code></li><li><code>GetStringMapString(key string) : map[string]string</code></li><li><code>GetStringSlice(key string) : []string</code></li><li><code>GetTime(key string) : time.Time</code></li><li><code>GetDuration(key string) : time.Duration</code></li><li><code>IsSet(key string) : bool</code></li><li><code>AllSettings() : map[string]interface{}</code></li></ul><p>要认识到的一件重要事情是，<strong>每个 Get 函数如果找不到相应的配置，都将返回零值</strong>。要检查给定的 key 是否存在，使用 <code>IsSet()</code> 方法。</p><p>例:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>viper<span class="token punctuation">.</span><span class="token function">GetString</span><span class="token punctuation">(</span><span class="token string">&quot;logfile&quot;</span><span class="token punctuation">)</span> <span class="token comment">// case-insensitive Setting &amp; Getting</span>
<span class="token keyword">if</span> viper<span class="token punctuation">.</span><span class="token function">GetBool</span><span class="token punctuation">(</span><span class="token string">&quot;verbose&quot;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">&quot;verbose enabled&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="accessing-nested-keys" tabindex="-1"><a class="header-anchor" href="#accessing-nested-keys" aria-hidden="true">#</a> Accessing nested keys</h3><p>可以访问深层嵌套的 key。例如，如果加载了以下 JSON 文件：</p><div class="language-json ext-json line-numbers-mode"><pre class="language-json"><code><span class="token punctuation">{</span>
    <span class="token property">&quot;host&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">&quot;address&quot;</span><span class="token operator">:</span> <span class="token string">&quot;localhost&quot;</span><span class="token punctuation">,</span>
        <span class="token property">&quot;port&quot;</span><span class="token operator">:</span> <span class="token number">5799</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">&quot;datastore&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">&quot;metric&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">&quot;host&quot;</span><span class="token operator">:</span> <span class="token string">&quot;127.0.0.1&quot;</span><span class="token punctuation">,</span>
            <span class="token property">&quot;port&quot;</span><span class="token operator">:</span> <span class="token number">3099</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">&quot;warehouse&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">&quot;host&quot;</span><span class="token operator">:</span> <span class="token string">&quot;198.0.0.1&quot;</span><span class="token punctuation">,</span>
            <span class="token property">&quot;port&quot;</span><span class="token operator">:</span> <span class="token number">2112</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Viper 可以通过传递一个 <code>.</code> 分隔的键路径来访问嵌套字段：</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code><span class="token function">GetString</span><span class="token punctuation">(</span><span class="token string">&quot;datastore.metric.host&quot;</span><span class="token punctuation">)</span> <span class="token comment">// (returns &quot;127.0.0.1&quot;)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>这会遵守上面建立的优先规则;对路径的搜索将通过其余配置注册表级联，直到找到为止。</p><p>例如，给定的配置文件中，<code>datastore.metric.host</code> 和 <code>datastore.metric.port</code>都 已经定义（并且可以被覆盖）。 如果在默认情况下定义了 <code>datastore.metric.protocol</code>，Viper 也会找到它。</p><p>但是，如果 <code>datastore.metric</code> 被重写（通过标志，环境变量，<code>Set()</code> 方法，...），那么 <code>datastore.metric</code> 的所有子键都变为未定义，它们是 被更高优先级的配置“遮蔽”。</p><p>最后，如果存在与分隔的键路径匹配的键，则将返回其值。例。</p><div class="language-json ext-json line-numbers-mode"><pre class="language-json"><code><span class="token punctuation">{</span>
    <span class="token property">&quot;datastore.metric.host&quot;</span><span class="token operator">:</span> <span class="token string">&quot;0.0.0.0&quot;</span><span class="token punctuation">,</span>
    <span class="token property">&quot;host&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">&quot;address&quot;</span><span class="token operator">:</span> <span class="token string">&quot;localhost&quot;</span><span class="token punctuation">,</span>
        <span class="token property">&quot;port&quot;</span><span class="token operator">:</span> <span class="token number">5799</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">&quot;datastore&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">&quot;metric&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">&quot;host&quot;</span><span class="token operator">:</span> <span class="token string">&quot;127.0.0.1&quot;</span><span class="token punctuation">,</span>
            <span class="token property">&quot;port&quot;</span><span class="token operator">:</span> <span class="token number">3099</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token property">&quot;warehouse&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token property">&quot;host&quot;</span><span class="token operator">:</span> <span class="token string">&quot;198.0.0.1&quot;</span><span class="token punctuation">,</span>
            <span class="token property">&quot;port&quot;</span><span class="token operator">:</span> <span class="token number">2112</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

GetString(<span class="token string">&quot;datastore.metric.host&quot;</span>) <span class="token comment">// returns &quot;0.0.0.0&quot;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="extract-sub-tree" tabindex="-1"><a class="header-anchor" href="#extract-sub-tree" aria-hidden="true">#</a> Extract sub-tree</h3><p>从 Viper 中提取 <code>sub-tree</code>。</p><p>例如，<code>viper</code> 表示:</p><div class="language-json ext-json line-numbers-mode"><pre class="language-json"><code>app<span class="token operator">:</span>
  cache1<span class="token operator">:</span>
    max-items<span class="token operator">:</span> <span class="token number">100</span>
    item-size<span class="token operator">:</span> <span class="token number">64</span>
  cache2<span class="token operator">:</span>
    max-items<span class="token operator">:</span> <span class="token number">200</span>
    item-size<span class="token operator">:</span> <span class="token number">80</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>执行后:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>subv <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">Sub</span><span class="token punctuation">(</span><span class="token string">&quot;app.cache1&quot;</span><span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p><code>subv</code>表示:</p><div class="language-json ext-json line-numbers-mode"><pre class="language-json"><code>max-items<span class="token operator">:</span> <span class="token number">100</span>
item-size<span class="token operator">:</span> <span class="token number">64</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><p>假设我们有:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">NewCache</span><span class="token punctuation">(</span>cfg <span class="token operator">*</span>Viper<span class="token punctuation">)</span> <span class="token operator">*</span>Cache <span class="token punctuation">{</span><span class="token operator">...</span><span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>它根据格式为 <code>subv</code> 的配置信息创建缓存。 现在很容易分别创建这两个缓存:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>cfg1 <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">Sub</span><span class="token punctuation">(</span><span class="token string">&quot;app.cache1&quot;</span><span class="token punctuation">)</span>
cache1 <span class="token operator">:=</span> <span class="token function">NewCache</span><span class="token punctuation">(</span>cfg1<span class="token punctuation">)</span>

cfg2 <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">Sub</span><span class="token punctuation">(</span><span class="token string">&quot;app.cache2&quot;</span><span class="token punctuation">)</span>
cache2 <span class="token operator">:=</span> <span class="token function">NewCache</span><span class="token punctuation">(</span>cfg2<span class="token punctuation">)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="unmarshaling" tabindex="-1"><a class="header-anchor" href="#unmarshaling" aria-hidden="true">#</a> Unmarshaling</h3><p>你还可以选择 Unmarshaling 所有的值或特定得值到 struct，map 等。</p><p>有两种方法可以做到这一点:</p><ul><li><code>Unmarshal(rawVal interface{}) : error</code></li><li><code>UnmarshalKey(key string, rawVal interface{}) : error</code></li></ul><p>例:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> config <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	Port <span class="token builtin">int</span>
	Name <span class="token builtin">string</span>
	PathMap <span class="token builtin">string</span> <span class="token string">`mapstructure:&quot;path_map&quot;`</span>
<span class="token punctuation">}</span>

<span class="token keyword">var</span> C config

err <span class="token operator">:=</span> <span class="token function">Unmarshal</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>C<span class="token punctuation">)</span>
<span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
	t<span class="token punctuation">.</span><span class="token function">Fatalf</span><span class="token punctuation">(</span><span class="token string">&quot;unable to decode into struct, %v&quot;</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="marshalling-to-string" tabindex="-1"><a class="header-anchor" href="#marshalling-to-string" aria-hidden="true">#</a> Marshalling to string</h3><p>你可能需要将 viper 中保存的所有设置编组为字符串，而不是将其写入文件。使用 <code>AllSettings()</code> 返回的配置，使用你喜欢的 marshaller 格式。</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token punctuation">(</span>
    yaml <span class="token string">&quot;gopkg.in/yaml.v2&quot;</span>
    <span class="token comment">// ...</span>
<span class="token punctuation">)</span>

<span class="token keyword">func</span> <span class="token function">yamlStringSettings</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
    c <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">AllSettings</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	bs<span class="token punctuation">,</span> err <span class="token operator">:=</span> yaml<span class="token punctuation">.</span><span class="token function">Marshal</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span>
	<span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        t<span class="token punctuation">.</span><span class="token function">Fatalf</span><span class="token punctuation">(</span><span class="token string">&quot;unable to marshal config to YAML: %v&quot;</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
	<span class="token keyword">return</span> <span class="token function">string</span><span class="token punctuation">(</span>bs<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="viper-还是-vipers" tabindex="-1"><a class="header-anchor" href="#viper-还是-vipers" aria-hidden="true">#</a> Viper 还是 Vipers?</h2><p>Viper 是开箱你用的。使用 Viper 不需要配置或初始化。由于大多数应用程序都希望使用单个中央存储库进行配置，因此 viper 软件包提供了此功能。它类似于单例。</p><p>在上面的所有示例中，他们演示了使用 viper 的单例式方法。</p><h3 id="working-with-multiple-vipers" tabindex="-1"><a class="header-anchor" href="#working-with-multiple-vipers" aria-hidden="true">#</a> Working with multiple vipers</h3><p>你还可以创建多个不同的 viper 实例，以便在你的应用程序中使用。每个都有自己独特的配置和值集。每个都可以从不同的配置文件、键值存储区等读取。 viper 包支持的所有函数都在 viper 实例上有相应的镜像方法。</p><p>例:</p><div class="language-go ext-go line-numbers-mode"><pre class="language-go"><code>x <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
y <span class="token operator">:=</span> viper<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

x<span class="token punctuation">.</span><span class="token function">SetDefault</span><span class="token punctuation">(</span><span class="token string">&quot;ContentDir&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;content&quot;</span><span class="token punctuation">)</span>
y<span class="token punctuation">.</span><span class="token function">SetDefault</span><span class="token punctuation">(</span><span class="token string">&quot;ContentDir&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;foobar&quot;</span><span class="token punctuation">)</span>

<span class="token comment">//...</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当使用多个 viper 实例时，由用户来跟踪不同的 viper 实例。</p><h2 id="q-a" tabindex="-1"><a class="header-anchor" href="#q-a" aria-hidden="true">#</a> Q &amp; A</h2><p>Q: 为什么不使用 INI 文件?</p><p>A: Ini 文件非常糟糕。 没有标准格式，很难验证。Viper 旨在使用 JSON，TOML 或 YAML 文件。如果有人真的想要添加此功能，我很乐意将其合并。 你可以轻松指定应用程序允许的格式。</p><p>Q: 为什么称它为 “Viper”?</p><p>A: Viper 被设计成 <a href="https://github.com/spf13/cobra" target="_blank" rel="noopener noreferrer">Cobra</a> 的 <a href="http://en.wikipedia.org/wiki/Viper_(G.I._Joe)" target="_blank" rel="noopener noreferrer">companion</a>。虽然两者可以完全独立地运行， 但它们共同构成了一个强大的组合，以满足大部分应用程序的基础需求。</p><p>Q: 为什么称它为 “Cobra”?</p><p>A: 还有比 <a href="http://en.wikipedia.org/wiki/Cobra_Commander" target="_blank" rel="noopener noreferrer">commander</a> 更好的名字么？</p><!--]--><!--[--><!--]--></div><footer class="page-meta"><!----><div class="meta-item last-updated"><span class="meta-item-label">Last Updated: </span><!----></div><!----></footer><!----><!--[--><!--]--><!----></main><!--]--></div><div class="search-page" role="search"><span class="search-close"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 448 512" width="28" height="28" fill="currentColor"><path d="M224 416c-8.188 0-16.38-3.125-22.62-9.375l-192-192c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L224 338.8l169.4-169.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-192 192C240.4 412.9 232.2 416 224 416z"></path></svg></span><div class="gungnir-search-box"><input placeholder="$ grep ..." autocomplete="off" spellcheck="false" value><!----></div></div><div class="menu-btn-container"><div class="menu-btn-wrapper"><div class="menu-btn"><div style="" class="menu-btn-icon"><span></span><span></span><span></span></div><div style="display:none;" class="menu-text">0</div><svg class="menu-progress"><circle class="menu-border" cx="50%" cy="50%" r="48%" style="stroke-dasharray:0% 314.15926%;"></circle></svg></div><div class="menu-btn-child-wrapper"><div class="toggle-dark-button menu-btn-child" title="toggle dark mode"><svg class="ov-icon" style="font-size:1.2em;display:none;" aria-hidden="true" width="19.2" height="19.2" viewbox="-43.52 -43.52 599.04 599.04" fill="currentColor"><path d="M256 160c-52.9 0-96 43.1-96 96s43.1 96 96 96 96-43.1 96-96-43.1-96-96-96zm246.4 80.5l-94.7-47.3 33.5-100.4c4.5-13.6-8.4-26.5-21.9-21.9l-100.4 33.5-47.4-94.8c-6.4-12.8-24.6-12.8-31 0l-47.3 94.7L92.7 70.8c-13.6-4.5-26.5 8.4-21.9 21.9l33.5 100.4-94.7 47.4c-12.8 6.4-12.8 24.6 0 31l94.7 47.3-33.5 100.5c-4.5 13.6 8.4 26.5 21.9 21.9l100.4-33.5 47.3 94.7c6.4 12.8 24.6 12.8 31 0l47.3-94.7 100.4 33.5c13.6 4.5 26.5-8.4 21.9-21.9l-33.5-100.4 94.7-47.3c13-6.5 13-24.7.2-31.1zm-155.9 106c-49.9 49.9-131.1 49.9-181 0-49.9-49.9-49.9-131.1 0-181 49.9-49.9 131.1-49.9 181 0 49.9 49.9 49.9 131.1 0 181z"/></svg><svg class="ov-icon" style="font-size:1.2em;display:none;" aria-hidden="true" width="19.2" height="19.2" viewbox="-43.52 -43.52 599.04 599.04" fill="currentColor"><path d="M283.211 512c78.962 0 151.079-35.925 198.857-94.792 7.068-8.708-.639-21.43-11.562-19.35-124.203 23.654-238.262-71.576-238.262-196.954 0-72.222 38.662-138.635 101.498-174.394 9.686-5.512 7.25-20.197-3.756-22.23A258.156 258.156 0 00283.211 0c-141.309 0-256 114.511-256 256 0 141.309 114.511 256 256 256z"/></svg><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="-43.52 -43.52 599.04 599.04" fill="currentColor"><path d="M224 96l16-32 32-16-32-16-16-32-16 32-32 16 32 16 16 32zM80 160l26.66-53.33L160 80l-53.34-26.67L80 0 53.34 53.33 0 80l53.34 26.67L80 160zm352 128l-26.66 53.33L352 368l53.34 26.67L432 448l26.66-53.33L512 368l-53.34-26.67L432 288zm70.62-193.77L417.77 9.38C411.53 3.12 403.34 0 395.15 0c-8.19 0-16.38 3.12-22.63 9.38L9.38 372.52c-12.5 12.5-12.5 32.76 0 45.25l84.85 84.85c6.25 6.25 14.44 9.37 22.62 9.37 8.19 0 16.38-3.12 22.63-9.37l363.14-363.15c12.5-12.48 12.5-32.75 0-45.24zM359.45 203.46l-50.91-50.91 86.6-86.6 50.91 50.91-86.6 86.6z"/></svg></div><div class="menu-btn-child"><svg class="ov-icon" style="font-size:1.7999999999999998em;" aria-hidden="true" width="28.799999999999997" height="28.799999999999997" viewbox="-75.52 -43.52 599.04 599.04" fill="currentColor"><path d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"/></svg></div><div class="menu-btn-child"><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="-75.52 -43.52 599.04 599.04" fill="currentColor"><path d="M240.971 130.524l194.343 194.343c9.373 9.373 9.373 24.569 0 33.941l-22.667 22.667c-9.357 9.357-24.522 9.375-33.901.04L224 227.495 69.255 381.516c-9.379 9.335-24.544 9.317-33.901-.04l-22.667-22.667c-9.373-9.373-9.373-24.569 0-33.941L207.03 130.525c9.372-9.373 24.568-9.373 33.941-.001z"/></svg></div><!----><div class="toggle-sidebar-button menu-btn-child menu-btn-sidebar" title="toggle sidebar" aria-expanded="false" role="button" tabindex="0"><svg class="ov-icon" style="font-size:1.2em;" aria-hidden="true" width="19.2" height="19.2" viewbox="-1.6 -1.6 19.2 19.2" fill="currentColor"><path d="M14 2a1 1 0 011 1v10a1 1 0 01-1 1H2a1 1 0 01-1-1V3a1 1 0 011-1h12zM2 1a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V3a2 2 0 00-2-2H2z"/><path d="M3 4a1 1 0 011-1h2a1 1 0 011 1v8a1 1 0 01-1 1H4a1 1 0 01-1-1V4z"/></svg></div></div></div></div><!----></div><!--]--></div>
    <script type="module" src="/assets/app.80e5dc69.js" defer></script>
  </body>
</html>
